<template>
  <div class="right-panel">
    <div class="control-section">
      <!-- 对话 -->
      <div class="chat-container">
        <div class="messages" style="height: 500px">
          <div
            v-for="(message, index) in messages"
            :key="index"
            :class="[
              'message',
              message.sender === 'user' ? 'message-user' : 'message-ai',
            ]"
          >
            <template v-if="message.sender === 'user'">
              <div class="message-box message-box-user">
                <!-- 显示选中的文件 -->
                <div v-if="message.files?.length" class="check-file-list">
                  <div
                    v-for="(file, fileIndex) in message.files"
                    :key="fileIndex"
                    class="file-item"
                  >
                    <div class="file-icon">
                      <img src="@/assets/img/doc-icon.png" alt="" />
                    </div>
                    <div class="file-details">
                      <div class="file-name">{{ file.fileName }}</div>
                      <div class="file-size">{{ file.fileSize }}</div>
                    </div>
                  </div>
                </div>
                <div class="user-message-content">
                  <div v-html="message.text"></div>
                </div>
              </div>
              <img :src="userAvatar" class="user-avatar" />
            </template>
            <template v-else>
              <img :src="aiAvatar" class="ai-avatar" />
              <div class="message-box message-box-ai">
                <!-- 显示选中的文件 -->
                <div v-if="message.files?.length" class="check-file-list">
                  <div
                    v-for="(file, fileIndex) in message.files"
                    :key="fileIndex"
                    class="file-item"
                  >
                    <div class="file-icon">
                      <img src="@/assets/img/doc-icon.png" alt="" />
                    </div>
                    <div class="file-details">
                      <div class="file-name">{{ file.fileName }}</div>
                      <div class="file-size">{{ file.fileSize }}</div>
                    </div>
                  </div>
                </div>
                <div class="message-content">
                  <!-- 当消息为空且正在发送时显示加载动画 -->
                  <div v-if="!message.text && isSending" class="loading-dots">
                    <span></span>
                    <span></span>
                    <span></span>
                  </div>
                  <div class="markdownContent" v-else>
                    <mdEditor
                      :toolbars="[]"
                      :footers="[]"
                      ref="mavonEditor"
                      class="mdEditor"
                      v-model="message.text"
                    />
                  </div>
                </div>
                <!-- 数字人视频及文档 -->
                <div
                  class="videoAndDocs"
                  v-if="
                    message.videoData ||
                    (message.documents && message.documents.length > 0)
                  "
                >
                  <!-- 数字人视频 -->
                  <div
                    class="video"
                    v-if="message.videoData && message.videoData.length > 0"
                    @click="playDigitalHumanVideo(message.videoData[0])"
                  >
                    <div class="video-img">
                      <img
                        :src="
                          message.videoData[0]?.picUrl ||
                          '@/assets/img/xiaodian.png'
                        "
                        alt=""
                      />
                    </div>
                    <div class="video-title">
                      <span>数字人解答</span>
                      <span
                        ><el-icon><VideoPlay /></el-icon>
                      </span>
                    </div>
                  </div>
                  <!-- 相关文档 -->
                  <div
                    class="docs"
                    v-if="message.documents && message.documents.length > 0"
                  >
                    <div
                      @click="openDoc(item)"
                      class="doc-item"
                      v-for="item in message.documents"
                      :key="item.id"
                    >
                      <div class="doc-item-img">
                        <img
                          :src="getDocIcon(item.title || item.name)"
                          alt=""
                        />
                      </div>
                      <div class="doc-item-info">
                        <span class="doc-item-title">{{
                          item.title || item.name
                        }}</span>
                        <span class="doc-item-size">{{ item.size }}</span>
                      </div>
                    </div>
                  </div>
                </div>
                <!-- 复制按钮和操作按钮 -->
                <div
                  class="action-buttons-container"
                  v-if="
                    message.text &&
                    (!isSending || index !== messages.length - 1)
                  "
                >
                  <!-- 复制按钮 -->
                  <div class="copy-button" @click="copyMessage(message.text)">
                    <el-icon><CopyDocument /></el-icon>
                    <span>复制</span>
                  </div>

                  <!-- 进入考核按钮 -->
                  <div
                    class="action-button enter-test-button"
                    v-if="
                      (message.sseResource &&
                        message.sseResource.courseTestButton === 1) ||
                      message.courseTestButton === 1
                    "
                    @click="
                      handleEnterTest(
                        message.sseResource?.courseTestButtonName ||
                          message.courseTestButtonName,
                        message.sseResource?.courseTestButtonId ||
                          message.courseTestButtonId
                      )
                    "
                  >
                    <span>进入考核</span>
                  </div>

                  <!-- 下一个知识点按钮 -->
                  <div
                    class="action-button next-button"
                    v-if="
                      (message.sseResource &&
                        message.sseResource.nextButton === 1) ||
                      message.nextButton === 1
                    "
                    @click="handleNextKnowledge()"
                  >
                    <span>下一个知识点</span>
                  </div>

                  <!-- 停止考核按钮 -->
                  <div
                    class="action-button stop-test-button"
                    v-if="
                      (message.sseResource &&
                        message.sseResource.stopButton === 1) ||
                      message.stopButton === 1
                    "
                    @click="handleStopTest()"
                  >
                    <span>停止考核</span>
                  </div>
                </div>
              </div>
            </template>
          </div>
        </div>

        <!-- 停止响应按钮 -->
        <div class="stop-response" v-if="isSending" @click="stopResponse()">
          <span @mouseover="stopHover = true" @mouseleave="stopHover = false">
            <img :src="stopHover ? stopImg1 : stopImg0" alt="" />
            停止响应
          </span>
        </div>

        <!-- 输入框 -->
        <div class="input-container">
          <!-- 添加新对话 -->
          <!-- <div class="add-chat" @click="addChat()"><img src="@/assets/img/新增对话.png" alt=""></div> -->
          <!-- 引用内容盒子 -->
          <div class="quote-box" v-if="quotedText">
            <span class="quoted-content">{{ quotedText }}</span>
            <i
              class="el-icon-close"
              @click="clearQuote"
              style="cursor: pointer"
            ></i>
          </div>
          <el-input
            class="sendInput"
            type="textarea"
            v-model="userInput"
            @keydown="handleKeyCode($event)"
            placeholder="请输入您想问的内容，按 Shift + Enter 换行"
            :style="{ border: 'none' }"
            :resize="'none'"
            :disabled="inputDisabled || endStatus === 1"
          />
          <div class="foot-btn">
            <div class="foot-left">
              <!-- 清空对话按钮 -->
              <!-- <div class="clear-chat" @click="clearChat()">
                <span
                  @mouseover="clearHover = true"
                  @mouseleave="clearHover = false"
                >
                  <img
                    :src="clearHover ? clearImg1 : clearImg0"
                    alt=""
                    style="width: 10px; height: 12px"
                  />
                  清空对话
                </span>
              </div> -->
              <!-- 上传 -->
              <!-- <div class="upload-btn">
                <el-upload
                  ref="upload"
                  class="upload-component"
                  action="/tes/experiment/course-review-fileupload"
                  :limit="1"
                  :show-file-list="false"
                  :before-upload="handleUpload"
                  :on-success="handleSuccess"
                >
                  <el-tooltip
                    class="item"
                    effect="dark"
                    content="支持上传文件：pdf，doc，xlsx，ppt，txt等"
                    placement="top"
                  >
                    <span>
                      <i class="iconfont icon-shangchuan1"></i>上传文件
                    </span>
                  </el-tooltip>
                </el-upload>
              </div> -->
            </div>
            <!-- 发送 -->
            <div class="foot-right">
              <el-button
                type="primary"
                :disabled="isSending || inputDisabled || endStatus === 1"
                @click="sendMessage"
                class="send-button"
                >发送</el-button
              >
            </div>
          </div>
        </div>
      </div>
    </div>

    <!-- 数字人 -->
    <div class="shuziren" v-if="shuzirenPic">
      <div class="img"><img :src="shuzirenPic" alt="" /></div>
      <div class="close">
        <el-icon><Close /></el-icon>
      </div>
    </div>

    <!-- 数字人语音 -->
    <div class="shuziren-audio" style="display: none">
      <audio
        ref="shuzirenAudio"
        :src="zhuzirenAudio"
        @ended="onAudioEnded"
      ></audio>
    </div>

    <!-- 视频播放弹窗 -->
    <el-dialog v-model="videoDialogVisible" title="数字人解答" width="40%">
      <video width="100%" height="400" controls>
        <source :src="videoData.url" type="video/mp4" />
      </video>
    </el-dialog>
  </div>
</template>

<script>
import clearImg0 from "@/assets/img/清空对话0.png";
import clearImg1 from "@/assets/img/清空对话1.png";
import stopImg0 from "@/assets/img/停止0.png";
import stopImg1 from "@/assets/img/停止1.png";
import aiAvatar from "@/assets/img/lu-icon.png";
import userAvatar from "@/assets/img/stu-icon.png";
import docIcon from "@/assets/img/doc-icon.png";
import pdfIcon from "@/assets/img/pdf-icon.png";
import excelIcon from "@/assets/img/xlsx-icon.png";
export default {
  props: {
    id: {
      type: Number,
    },
    cId: {
      type: Number,
      default: null,
    },
  },
  data() {
    return {
      courseId: "",
      uploadedFiles: [],
      userInput: "",
      messages: [],
      messageRecord: [],
      aiAvatar,
      userAvatar,
      selectedFileIndex: [],
      isSelected: false, // 用于跟踪当前选择状态
      quotedText: "", // 新增引用文本
      uploadLoading: false,
      eventSource: null,
      connectId: null,
      fileId: null,
      isSending: false,
      stopHover: false,
      clearHover: false,
      sessionId: "",
      sseUrl: "",
      clearImg0,
      clearImg1,
      stopImg0,
      stopImg1,
      videoDialogVisible: false,
      videoData: null,
      sseResource: "", // sse资源数据
      isCollectingJson: false, // 标记是否正在收集JSON数据
      jsonBuffer: "", // 临时存储JSON数据
      kbId: null, // 知识库ID，用于进入考核时传递
      shuzirenPic: "",
      shuzirenPid: "",
      zhuzirenAudio: "",
      inputDisabled: false, // 控制输入框禁用状态
      classId: null,
      chapterId: null,
      endStatus: null, // 结束状态
    };
  },
  watch: {
    id: {
      handler(newVal) {
        this.chapterId = newVal;
        this.getChatRecord();
      },
    },
    cId: {
      handler(newVal) {
        this.classId = newVal;
        this.getChatRecord();
      },
    },
  },
  created() {
    this.courseId = JSON.parse(localStorage.getItem("courseId"));
    // this.getFileList();
    this.getSessionId();
  },

  methods: {
    // 获取聊天记录
    getChatRecord() {
      const loading = this.$loading({
        lock: true,
        text: "加载中...",
        spinner: "el-icon-loading",
        background: "rgba(0, 0, 0, 0.7)",
      });
      this.$axios
        .get(
          `/tes/course/auto/make/list-record?contextId=${this.chapterId}&courseId=${this.courseId}&type=3&classId=${this.classId}`
        )
        .then((res) => {
          this.messageRecord = res.data.record || [];
          this.endStatus = res.data.endStatus;
          if (this.messageRecord.length > 0) {
            this.sessionId = res.data.sessionId;
            // 有聊天记录，处理并展示记录
            this.processChatHistory(this.messageRecord);
          } else {
            // 无聊天记录，调用新的对话接口
            this.callDialogueAPI("开始");
          }
        })
        .finally(() => {
          loading.close();
        });
    },

    // 新增：调用对话接口
    callDialogueAPI(prompt) {
      // 获取用户信息
      const userInfo = JSON.parse(localStorage.getItem("userInfo") || "{}");
      const userId = userInfo.id;

      if (!userId) {
        this.$message.error("获取用户信息失败");
        return;
      }

      // 先添加AI消息占位符（仅在开始时）
      if (prompt === "开始") {
        const aiMessage = {
          sender: "assistant",
          text: "",
          isWelcome: true,
          videoData: null,
          documents: [],
          sseResource: null,
        };
        this.messages.push(aiMessage);
        this.isSending = true;
      }

      // 建立SSE连接
      this.connectEventSource(() => {
        // 连接建立后调用对话接口
        const requestData = {
          prompt: prompt,
          connectId: this.connectId,
          sessionId: this.sessionId,
          userId: userId,
          agentId: this.chapterId, // 考核id，为左侧列表点击传过来的id
        };

        this.$axios
          .post("/tes/graph/assess/agent/dialogue", requestData)
          .then((res) => {
            console.log("对话接口调用成功:", res);
          })
          .catch((error) => {
            console.warn("对话接口调用失败:", error);
            this.isSending = false;
          });
      });
    },

    // 处理聊天历史记录
    processChatHistory(records) {
      // 清空当前messages，保留欢迎语之外的内容
      this.messages = [];

      records.forEach((record) => {
        // 处理用户消息
        if (record.role == "user") {
          const userMessage = {
            sender: "user",
            text: record.content?.replace(/\n/g, "<br>") || "",
          };
          this.messages.push(userMessage);
        }

        // 处理AI回复消息
        if (record.role == "assistant") {
          const aiMessage = {
            sender: "assistant",
            text: record.content?.replace(/\\n/g, "<br>") || "",
            files: record.files || [],
            isWelcome: false,
            videoData: record.video || null, // 数字人视频数据
            documents: record.resources || [], // 文档数据
            sseResource: record.sseResource || null, // SSE资源数据
            nextButton: record.nextButton || null, // 下一题按钮
            stopButton: record.stopButton || null, // 停止按钮
            courseTestButton: record.courseTestButton || null, // 进入考核按钮
            courseTestButtonName: record.courseTestButtonName || null, // 进入考核按钮名称
            courseTestButtonId: record.courseTestButtonId || null, // 进入考核按钮id
          };
          this.messages.push(aiMessage);
        }
      });

      // 滚动到最新消息
      this.$nextTick(() => {
        const messagesContainer = this.$el.querySelector(".messages");
        if (messagesContainer) {
          messagesContainer.scrollTop = messagesContainer.scrollHeight;
        }
      });
    },

    getSessionId() {
      const characters =
        "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
      let result = "";
      for (let i = 0; i < 16; i++) {
        result += characters.charAt(
          Math.floor(Math.random() * characters.length)
        );
      }
      this.sessionId = result;
    },
    // 获取文件列表
    getFileList() {
      this.$axios
        .get("/tes/experiment/course-review-filelist?type=1")
        .then((res) => {
          if (res.data.code === 200) {
            this.uploadedFiles = res.data.data;
          }
        });
    },
    // 发送消息
    sendMessage() {
      if (this.userInput.trim() === "") {
        this.$message.error("请输入您想问的内容");
        this.userInput = "";
        return;
      }

      if (this.isSending) {
        this.$message.error("请等待上一次对话结束");
        return;
      }

      if (this.inputDisabled || this.endStatus === 1) {
        this.$message.error("当前考核已结束");
        return;
      }

      // 添加user消息
      const newMessage = {
        sender: "user",
        quotedText: this.quotedText ? this.quotedText : "",
        text: this.userInput.replace(/\n/g, "<br>"),
        files: this.selectedFileIndex.map((index) => this.uploadedFiles[index]),
      };
      this.messages.push(newMessage);

      // 添加AI消息占位
      const aiMessage = {
        sender: "assistant",
        text: "",
        files: [],
        isWelcome: false,
      };
      this.messages.push(aiMessage);

      // 调用对话接口
      this.callDialogueAPI(this.userInput);

      // 清空输入框和选中的文件
      const currentInput = this.userInput;
      this.userInput = "";
      this.quotedText = "";
      this.isSending = true;

      // 滚动到最新消息
      this.$nextTick(() => {
        const messagesContainer = this.$el.querySelector(".messages");
        messagesContainer.scrollTop = messagesContainer.scrollHeight;
      });
    },

    // 建立sse连接
    connectEventSource(callback) {
      const that = this;

      if (window.EventSource) {
        // 如果已经存在连接，先关闭
        if (this.eventSource) {
          this.eventSource.close();
        }

        // 重置JSON收集状态
        this.isCollectingJson = false;
        this.jsonBuffer = "";
        this.sseResource = "";

        this.eventSource = new EventSource(`/tes/course/auto/make/sse/connect`);

        this.eventSource.onmessage = function (event) {
          const connectId = event.lastEventId;
          const data = event.data;

          if (connectId === data) {
            // 获取到连接id后执行回调
            that.connectId = connectId;
            if (callback) {
              callback();
            }
          } else {
            // 处理返回的消息流
            let currentMessage = that.messages[that.messages.length - 1];

            // 检查是否开始收集JSON数据
            if (data === "↖sseDone↘") {
              that.isCollectingJson = true;
              that.jsonBuffer = "";
              return;
            }

            // 检查是否结束收集JSON数据
            if (data === "↖Done↘") {
              if (that.isCollectingJson) {
                // 处理收集到的JSON数据
                try {
                  const parsedJson = JSON.parse(that.jsonBuffer);
                  that.sseResource = parsedJson;
                  console.log("提取到的JSON资源数据:", parsedJson);

                  // 检查 end 字段，如果为 1 则禁用输入框
                  if (parsedJson.end == 1) {
                    that.inputDisabled = true;
                  }

                  // 将sseResource数据存储到当前AI消息中，同时处理视频和文档资源
                  let currentMessage = that.messages[that.messages.length - 1];
                  if (currentMessage && currentMessage.sender === "assistant") {
                    currentMessage.sseResource = parsedJson;
                    // 处理视频数据
                    if (parsedJson.video && parsedJson.video.length > 0) {
                      currentMessage.videoData = parsedJson.video;
                    }
                    // 处理文档资源
                    if (
                      parsedJson.resources &&
                      parsedJson.resources.length > 0
                    ) {
                      currentMessage.documents = parsedJson.resources;
                    }
                  }
                } catch (error) {
                  console.warn(
                    "JSON解析失败:",
                    error,
                    "原始数据:",
                    that.jsonBuffer
                  );
                  // 如果解析失败，保存原始字符串
                  that.sseResource = that.jsonBuffer;

                  // 同样存储到当前AI消息中
                  let currentMessage = that.messages[that.messages.length - 1];
                  if (currentMessage && currentMessage.sender === "assistant") {
                    currentMessage.sseResource = that.jsonBuffer;
                  }
                }

                // 重置收集状态
                that.isCollectingJson = false;
                that.jsonBuffer = "";
              }

              // SSE流结束
              that.isSending = false;
              that.eventSource.close();
              that.eventSource = null;
              return;
            }

            // 如果正在收集JSON数据，将data添加到缓冲区
            if (that.isCollectingJson) {
              that.jsonBuffer += data;
              return;
            }

            // 确保当前消息是AI消息，且不在收集JSON状态
            if (currentMessage && currentMessage.sender === "assistant") {
              // 处理特殊字符
              let processedData = data
                .replaceAll("↖emsp↘", " ")
                .replaceAll("↖Start↘", "")
                .replaceAll("↖br↘", "\n")
                .replaceAll("↖tab↘", "   ")
                .replaceAll("↖sseDone↘", "")
                .replaceAll("↖Done↘", "")
                // 处理每个字符都被双引号包围的情况（如："欢""迎" -> 欢迎）
                .replace(/"(.?)"/g, "$1")
                // 处理被分割的Unicode字符（如："\uD83D""\uDC49" -> \uD83D\uDC49）
                .replace(/"(\\u[0-9A-Fa-f]{4})""(\\u[0-9A-Fa-f]{4})"/g, "$1$2")
                // 处理单独的Unicode字符
                .replace(/"(\\u[0-9A-Fa-f]{4})"/g, "$1")
                // 将Unicode转义序列转换为实际字符（处理代理对）
                .replace(
                  /\\u([0-9A-Fa-f]{4})\\u([0-9A-Fa-f]{4})/g,
                  (match, high, low) => {
                    const highCode = parseInt(high, 16);
                    const lowCode = parseInt(low, 16);
                    // 检查是否为代理对
                    if (
                      highCode >= 0xd800 &&
                      highCode <= 0xdbff &&
                      lowCode >= 0xdc00 &&
                      lowCode <= 0xdfff
                    ) {
                      return String.fromCharCode(highCode, lowCode);
                    }
                    // 否则单独处理每个字符
                    return (
                      String.fromCharCode(highCode) +
                      String.fromCharCode(lowCode)
                    );
                  }
                )
                // 处理单独的Unicode字符
                .replace(/\\u([0-9A-Fa-f]{4})/g, (match, code) => {
                  return String.fromCharCode(parseInt(code, 16));
                })
                // 处理字面的换行符字符串
                .replaceAll('\\"n\\"', "\n")
                .replaceAll('"\\n"', "\n")
                .replaceAll("\\n", "\n")
                // 处理其他转义字符
                .replaceAll("\\t", "\t")
                .replaceAll('\\"', '"');

              // 更新markdown内容
              currentMessage.text += processedData;

              that.$nextTick(() => {
                // 滚动到底部
                const messagesContainer = that.$el.querySelector(".messages");
                if (messagesContainer) {
                  messagesContainer.scrollTop = messagesContainer.scrollHeight;
                }
              });
            }
          }
        };

        this.eventSource.onerror = function (error) {
          that.eventSource.close();
          that.eventSource = null;
          that.isSending = false;
        };
      } else {
        this.$message.error("您的浏览器不支持 SSE，请更换浏览器");
        that.isSending = false;
      }
    },

    // 上传前
    handleUpload(file) {
      this.uploadLoading = this.$loading({
        lock: true,
        text: "上传中...",
        spinner: "el-icon-loading",
        background: "rgba(0, 0, 0, 0.7)",
      });
      const isDOC = file.name.endsWith(".doc") || file.name.endsWith(".docx");
      if (!isDOC) {
        this.$message.error("只能上传.doc或.docx格式的文件！");
        this.uploadLoading.close();
        return false;
      }
    },

    // 上传成功
    handleSuccess(response, file, fileList) {
      if (response.code === 200) {
        this.getFileList();
        this.uploadLoading.close();
        // 重置上传组件
        this.$refs.upload.clearFiles();
      } else {
        this.$message.error(response.msg);
        this.uploadLoading.close();
      }
    },

    // 删除文件
    delFile(id) {
      this.$axios
        .delete("/tes/experiment/course-review-filedelete?fileId=" + id)
        .then((res) => {
          if (res.data.code === 200) {
            this.$message.success("删除成功");
            // 如果删除的是当前选中的文件，重置选择状态
            if (this.fileId === id) {
              this.fileId = null;
              this.selectedFileIndex = [];
            }
            this.getFileList();
          }
        });
    },

    // 左右滑动文件列表
    scrollLeft() {
      const stepBox = this.$refs.stepBox;
      stepBox.scrollBy({
        left: -200,
        behavior: "smooth",
      });
    },
    scrollRight() {
      const stepBox = this.$refs.stepBox;
      stepBox.scrollBy({
        left: 200,
        behavior: "smooth",
      });
    },

    // 复制消息
    copyMessage(text) {
      try {
        if (navigator.clipboard) {
          navigator.clipboard.writeText(text).then(() => {
            this.$message.success("消息已复制到剪贴板");
          });
        } else {
          // 降级处理 - 使用传统方法
          const textarea = document.createElement("textarea");
          textarea.value = text;
          document.body.appendChild(textarea);
          textarea.select();
          document.execCommand("copy");
          document.body.removeChild(textarea);
          this.$message.success("消息已复制到剪贴板");
        }
      } catch (err) {
        this.$message.error("复制失败，请手动复制");
      }
    },

    // 删除消息
    deleteMessage(index) {
      this.messages.splice(index, 1);
    },

    // 引用消息
    quoteMessage(text) {
      this.quotedText = `"  ${text}   "`;
      this.userInput = "";
    },

    // 重新生成消息
    resetSend(index) {
      // 删除当前AI回复的消息
      this.messages.splice(index, 1);

      // 获取上一条user消息
      const userMessage = this.messages[index - 1];

      // 添加新的AI消息占位
      const aiMessage = {
        sender: "assistant",
        text: "",
        files: [],
        isWelcome: false, // 标记这不是欢迎语
      };
      this.messages.push(aiMessage);

      this.isSending = true;

      // 滚动到最新消息
      this.$nextTick(() => {
        const messagesContainer = this.$el.querySelector(".messages");
        messagesContainer.scrollTop = messagesContainer.scrollHeight;
      });
    },

    // 换行处理
    handleKeyCode(event) {
      if (event.keyCode === 13) {
        if (event.shiftKey) {
          return;
        } else {
          event.preventDefault();
          this.sendMessage();
        }
      }
    },

    // 选中文件
    toggleFileSelection(index, id) {
      // 更新选中状态
      this.selectedFileIndex = [index];
      this.fileId = id;
    },

    toggleSelection() {
      this.isSelected = !this.isSelected; // 切换选择状态
    },

    clearQuote() {
      this.quotedText = "";
    },

    addChat() {
      if (this.isSending) {
        this.$message.error("请等待上一次对话结束");
        return;
      }

      // 在最后一条消息后添加分割线
      const divider = document.createElement("div");
      divider.style.textAlign = "center";
      divider.style.width = "80%";
      divider.style.color = "#999";
      divider.style.margin = "10px 0";
      divider.innerText =
        "-----------------------------------------以下是新消息-----------------------------------------";

      const messagesContainer = this.$el.querySelector(".messages");
      messagesContainer.appendChild(divider);
      // 清空消息列表
      // this.messages = [];

      // 添加新的欢迎语
      this.messages.push({
        sender: "assistant",
        text: "我擅长为企业打造专属营销内容，让你的产品更具吸引力。",
        files: [],
        isWelcome: true, // 添加标记表示这是欢迎语
      });
      // 清空其他状态
      this.userInput = "";
      this.selectedFileIndex = [];
      // this.quotedText = "";
      this.fileId = null;
      this.getSessionId();
      // 滚动到最新消息
      this.$nextTick(() => {
        const messagesContainer = this.$el.querySelector(".messages");
        messagesContainer.scrollTop = messagesContainer.scrollHeight;
      });
    },

    // 停止响应
    stopResponse() {
      if (this.connectId) {
        this.$axios
          .get(`/tes/experiment/stop/${this.connectId}`)
          .then((res) => {
            if (res.data.code === 200) {
              this.$message.success("已停止响应");
              this.isSending = false;
              if (this.eventSource) {
                this.eventSource.close();
                this.eventSource = null;
              }
            }
          })
          .catch((err) => {
            console.error("停止响应失败:", err);
            this.$message.error("停止响应失败");
          });
      }
    },

    // 清空对话方法
    clearChat() {
      if (this.isSending) {
        this.$message.error("请等待上一次对话结束");
        return;
      }
      this.$confirm("确定清空对话吗？", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      }).then(() => {
        this.$axios
          .delete(
            `/tes/course/auto/make/delete-record?sessionId=${this.sessionId}`
          )
          .then((res) => {
            this.$message.success("清空对话成功");
            this.messages = [];
            this.userInput = "";
            this.inputDisabled = false; // 重置输入框禁用状态
            this.getSessionId();
            this.getChatRecord();
          });
      });
    },

    // 播放数字人视频
    playDigitalHumanVideo(videoData) {
      if (videoData && videoData.url) {
        this.videoDialogVisible = true;
        this.videoData = videoData;
      } else {
        this.$message.warning("视频数据不可用");
      }
    },

    // 处理进入考核按钮点击
    handleEnterTest(courseTestButtonName, courseTestButtonId) {
      if (this.isSending) {
        this.$message.error("请等待上一次对话结束");
        return;
      }

      this.kbId = courseTestButtonId; // 设置知识库ID
      const message = `请提供与${courseTestButtonName}相关的知识点考题`;
      this.userInput = message;
      this.sendMessage();
    },

    // 处理下一个知识点按钮点击
    handleNextKnowledge() {
      if (this.isSending) {
        this.$message.error("请等待上一次对话结束");
        return;
      }

      const message = "我已掌握当前知识点，请继续讲解下一个知识点";
      this.userInput = message;
      this.sendMessage();
    },

    // 处理停止考核按钮点击
    handleStopTest() {
      if (this.isSending) {
        this.$message.error("请等待上一次对话结束");
        return;
      }

      const message = "我已掌握当前知识点，考题暂停，请继续讲解下一个知识点";
      this.userInput = message;
      this.sendMessage();
    },

    // 打开文档
    openDoc(item) {
      window.open(item.url, "_blank");
    },
    // 获取文档图标
    getDocIcon(fileName) {
      if (!fileName) return docIcon;
      const lowerCaseFileName = fileName.toLowerCase();
      if (
        lowerCaseFileName.endsWith(".doc") ||
        lowerCaseFileName.endsWith(".docx")
      ) {
        return docIcon;
      } else if (lowerCaseFileName.endsWith(".pdf")) {
        return pdfIcon;
      } else if (
        lowerCaseFileName.endsWith(".xlsx") ||
        lowerCaseFileName.endsWith(".xls")
      ) {
        return excelIcon;
      } else {
        return docIcon;
      }
    },

    // 重置对话 - 清空聊天记录并重新获取开场白
    resetChat() {
      // 如果正在发送，先停止
      // if (this.isSending) {
      //   this.stopResponse();
      // }

      // 关闭现有的SSE连接
      if (this.eventSource) {
        this.eventSource.close();
        this.eventSource = null;
      }

      // 清空消息列表
      this.messages = [];

      // 清空输入框和其他状态
      this.userInput = "";
      this.quotedText = "";
      this.selectedFileIndex = [];
      this.fileId = null;
      this.isSending = false;
      this.inputDisabled = false; // 重置输入框禁用状态

      // 重置其他状态
      this.isCollectingJson = false;
      this.jsonBuffer = "";
      this.sseResource = "";

      // 生成新的sessionId
      this.getSessionId();
    },

    // 播放数字人语音
    playShuzirenAudio() {
      if (this.$refs.shuzirenAudio && this.zhuzirenAudio) {
        this.$refs.shuzirenAudio.play().catch((error) => {
          console.warn("数字人语音播放失败:", error);
        });
      }
    },

    // 数字人语音播放结束
    onAudioEnded() {
      console.log("数字人语音播放结束");
      // 可以在这里添加语音播放结束后的处理逻辑
    },
  },
};
</script>

<style lang="scss" scoped>
.right-panel {
  position: relative;
  width: 100%;
  max-height: 650px;
  display: flex;
  flex-direction: column;
  box-sizing: border-box;

  .control-section {
    padding: 10px 20px 0;
    background-color: #f3f5fa;
    display: flex;
    flex-direction: column;
    align-items: center;
    box-sizing: border-box;

    .upload-area {
      display: flex;
      justify-content: flex-start;
      align-items: center;
      .addFiles {
        width: 65px;
        height: 65px;
        background: #ffffff;
        box-shadow: 1px 2px 6px 0px rgba(0, 0, 0, 0.11);
        border-radius: 10px;
        border: 1px solid #e5e5e5;
        display: flex;
        flex-direction: column;
        justify-content: center;
        align-items: center;
        i {
          font-size: 18px;
          margin-bottom: 5px;
        }
        &:hover {
          color: #1c4fe5;
        }
      }
      .file-list-content {
        width: 100%;

        position: relative;
        .arrow-left {
          position: absolute;
          left: 15px;
          top: 30%;
          width: 30px;
          height: 30px;
          text-align: center;
          line-height: 30px;
          border-radius: 50%;
          background-color: rgba(0, 0, 0, 0.5);
          color: #fff;
          z-index: 999;
          cursor: pointer;
          &:hover {
            background-color: rgba(0, 0, 0, 0.7);
          }
        }
        .arrow-right {
          position: absolute;
          right: -35px;
          top: 30%;
          width: 30px;
          height: 30px;
          text-align: center;
          line-height: 30px;
          border-radius: 50%;
          background-color: rgba(0, 0, 0, 0.5);
          color: #fff;
          z-index: 999;
          cursor: pointer;
          &:hover {
            background-color: rgba(0, 0, 0, 0.7);
          }
        }
        .file-list {
          position: relative;
          margin-left: 50px;
          width: 1000px;
          height: 80px;
          overflow-x: hidden;
          display: flex;
          justify-content: flex-start;
          align-items: center;
          li {
            position: relative;
            flex-shrink: 0;
            display: flex;
            justify-content: flex-start;
            align-items: center;
            width: 200px;
            height: 65px;
            padding: 15px 18px;
            background: #ffffff;
            box-shadow: 1px 2px 6px 0px rgba(0, 0, 0, 0.11);
            border-radius: 10px;
            margin-right: 20px;
            box-sizing: border-box;
            cursor: pointer;
            .removeFile {
              position: absolute;
              top: -7px;
              right: -7px;
              z-index: 99;
            }
            .file-icon {
              width: 25px;
              height: 33px;
              img {
                width: 100%;
              }
            }
            .file-details {
              display: flex;
              flex-direction: column;
              align-items: flex-start;
              margin-left: 17px;
              .file-name {
                font-size: 14px;
                color: #000000;
                overflow: hidden;
                white-space: nowrap;
                text-overflow: ellipsis;
                max-width: 120px;
              }
              .file-size {
                font-size: 12px;
                color: #909090;
                margin-top: 10px;
              }
            }
          }
        }
      }
    }

    .chat-container {
      display: flex;
      flex-direction: column;
      width: 100%;
      height: calc(100vh - 280px);
      padding-bottom: 10px;
      position: relative;
      box-sizing: border-box;

      .messages {
        width: 100%;
        padding: 10px;
        min-height: 0;
        max-height: 100%;
        overflow-y: auto;
      }

      .message {
        display: flex;
        margin: 10px 0;
        box-sizing: border-box;
        width: 100%;
      }

      .message-user {
        justify-content: flex-end;
      }

      .message-ai {
        justify-content: flex-start;
      }

      .user-avatar {
        width: 40px;
        height: 40px;
        border-radius: 50%;
        margin-left: 10px;
      }

      .ai-avatar {
        width: 40px;
        height: 40px;
        border-radius: 50%;
        margin-right: 10px;
      }

      .message-box {
        max-width: calc(100% - 120px);
        border-radius: 10px;
        word-wrap: break-word;
        display: flex;
        flex-direction: column;
        .message-content {
          background-color: #fff;
          border-radius: 10px;
          line-height: 1.5;
          overflow: hidden;

          .markdownContent {
            .mdEditor {
              border: none;
              height: auto;
              // 隐藏头部工具栏
              // :deep(.md-editor-toolbar-wrapper) {
              //   display: none;
              //   padding: 0;
              // }
              // 隐藏底部
              // :deep(.md-editor-footer) {
              //   display: none;
              // }
              // 隐藏左侧编辑区
              :deep(.md-editor-input-wrapper) {
                display: none;
              }
              // 隐藏中间分割线
              :deep(.md-editor-resize-operate) {
                width: 0;
              }
              :deep(.md-editor-content-wrapper) {
                width: 100% !important;
              }
              :deep(.md-editor-content) {
                display: block;
              }
            }
          }
        }
        .videoAndDocs {
          margin-top: 10px;
          display: flex;
          justify-content: flex-start;
          align-items: flex-start;
          gap: 10px;
          .video {
            display: flex;
            align-items: center;
            justify-content: center;
            width: 215px;
            height: 100px;
            background: linear-gradient(90deg, #ffffff, #d2e0ff);
            border-radius: 10px;
            box-sizing: border-box;
            cursor: pointer;
            .video-img {
              width: 75px;
              height: 101px;
              img {
                width: 100%;
                height: 100%;
                object-fit: cover;
              }
            }
            .video-title {
              margin-left: 10px;
              display: flex;
              flex-direction: column;
              align-items: flex-end;
              justify-content: space-between;
              height: 70px;
              font-weight: bold;
              font-size: 16px;
              color: #457aff;
              .el-icon {
                font-size: 26px;
                color: #457aff;
              }
            }
          }
          .docs {
            display: flex;
            align-items: center;
            gap: 10px;
            .doc-item {
              padding: 8px 12px;
              display: flex;
              align-items: center;
              justify-content: center;
              gap: 10px;
              width: 170px;
              height: 55px;
              background: #ffffff;
              border-radius: 10px;
              cursor: pointer;
              box-sizing: border-box;
              .doc-item-img {
                flex-shrink: 0;
                width: 30px;
                height: 40px;
                img {
                  width: 100%;
                  height: 100%;
                  object-fit: cover;
                }
              }
              .doc-item-info {
                flex: 1;
                display: flex;
                flex-direction: column;
                align-items: flex-start;
                justify-content: center;
                .doc-item-title {
                  font-size: 12px;
                  color: #181818;
                  overflow: hidden;
                  white-space: nowrap;
                  text-overflow: ellipsis;
                  max-width: 96px;
                }
                .doc-item-size {
                  font-size: 12px;
                  color: #7c7c7c;
                }
              }
            }
          }
        }
        .user-message-content {
          max-width: 100%;
          padding: 10px 20px;
          background-color: #e0e4f9;
          border-radius: 10px;
          line-height: 1.5;

          .quote-box {
            white-space: nowrap; /* 不换行 */
            overflow: hidden; /* 超出部分隐藏 */
            text-overflow: ellipsis; /* 超出部分用省略号表示 */
            margin-bottom: 5px; /* 引用与消息内容之间的间距 */
            padding: 5px; /* 引用盒子的内边距 */
            background-color: #f3f4fa; /* 引用盒子的背景色 */
            border-radius: 5px; /* 圆角 */
          }
        }

        .action-buttons-container {
          margin-top: 10px;
          display: flex;
          align-items: center;
          gap: 8px;
          flex-wrap: wrap;
        }

        .copy-button {
          display: flex;
          align-items: center;
          justify-content: center;
          padding: 6px 12px;
          background-color: #f5f7fa;
          border-radius: 6px;
          cursor: pointer;
          font-size: 12px;
          color: #606266;
          transition: all 0.3s;
          width: fit-content;

          &:hover {
            background-color: #e4e7ed;
          }
        }

        .action-button {
          display: flex;
          align-items: center;
          justify-content: center;
          padding: 6px 12px;
          border-radius: 6px;
          cursor: pointer;
          font-size: 12px;
          transition: all 0.3s;
          width: fit-content;

          &.enter-test-button {
            background-color: #1c4fe5;
            color: #fff;

            &:hover {
              background-color: #0d3dbf;
            }
          }

          &.next-button {
            background-color: #67c23a;
            color: #fff;

            &:hover {
              background-color: #529b2e;
            }
          }

          &.stop-test-button {
            background-color: #f56c6c;
            color: #fff;

            &:hover {
              background-color: #f04147;
            }
          }
        }
      }

      .message-box-user {
        align-items: flex-end;
      }

      .message-box-ai {
        align-items: flex-start;
      }

      .check-file-list {
        display: flex;
        flex-wrap: wrap;
        justify-content: flex-start;
        align-items: center;
        .file-item {
          display: flex;
          justify-content: flex-start;
          align-items: center;
          width: 200px;
          height: 65px;
          padding: 15px 18px;
          background: #ffffff;
          box-shadow: 1px 2px 6px 0px rgba(0, 0, 0, 0.11);
          border-radius: 10px;
          margin-right: 20px;
          margin-bottom: 10px;
          box-sizing: border-box;
          .file-icon {
            width: 25px;
            height: 33px;
            img {
              width: 100%;
            }
          }
          .file-details {
            display: flex;
            flex-direction: column;
            align-items: flex-start;
            margin-left: 17px;
            .file-name {
              font-size: 14px;
              color: #000000;
              overflow: hidden;
              white-space: nowrap;
              text-overflow: ellipsis;
              max-width: 120px;
            }
            .file-size {
              font-size: 12px;
              color: #909090;
              margin-top: 10px;
            }
          }
        }
      }

      .action-buttons {
        max-width: 100%; /* 限制消息内容的最大宽度 */
        display: flex;
        justify-content: space-between;
        align-items: center;
        .item-right {
          flex: 1;
          text-align: right;
        }
      }
    }

    .input-container {
      display: flex;
      flex-direction: column;
      justify-content: space-around;
      max-width: 100%;
      margin-top: 10px;
      border-radius: 8px;
      height: 110px;
      // min-height: 100px;
      background-color: #fff;
      border: 1px solid #e5e5e5;

      // 添加媒体查询，处理150%缩放的情况
      @media screen and (max-width: 1200px),
        screen and (-webkit-min-device-pixel-ratio: 1.5),
        screen and (min-resolution: 144dpi) {
        width: 90%;
        margin-left: auto;
        margin-right: auto;
      }
      :deep(.el-textarea__inner) {
        border: none;
        // height: 80px;
        box-shadow: none;
      }
      .add-chat {
        position: absolute;
        top: 50%;
        transform: translateY(-50%);
        left: -50px;
        width: 40px;
        height: 40px;
        background: #ffffff;
        border-radius: 50%;
        border: 1px solid #e5e5e5;
        text-align: center;
        line-height: 40px;
        cursor: pointer;
        z-index: 1;

        // 在大屏幕缩放时调整位置
        @media screen and (max-width: 1200px),
          screen and (-webkit-min-device-pixel-ratio: 1.5),
          screen and (min-resolution: 144dpi) {
          left: -50px;
        }

        img {
          width: 17px;
          height: 17px;
          vertical-align: middle;
        }
      }
    }

    input {
      padding: 10px;
      width: calc(100% - 50px); /* 留出按钮的空间 */
      border: 1px solid #ccc;
      border-radius: 5px; /* 圆角 */
    }

    .stop-response {
      display: flex;
      justify-content: center;
      align-items: center;
      font-family: Microsoft YaHei;
      font-size: 14px;
      cursor: pointer;
      &:hover {
        color: #1c4fe5;
      }

      span {
        // padding: 5px 7px;
        width: 108px;
        height: 30px;
        background: #ffffff;
        box-shadow: 0px 2px 14px 0px rgba(43, 85, 191, 0.19);
        border-radius: 6px;
        border: 1px solid #e9ebf2;
        font-size: 14px;
        line-height: 32px;
        text-align: center;
        i {
          margin-right: 5px;
        }
        &:hover {
          color: #1c4fe5;
          border: 1px solid #1c4fe5;
        }
      }
    }
    .foot-btn {
      display: flex;
      justify-content: space-between;
      align-items: center;
      width: 100%;
      background: #ffffff;
      padding: 0 15px;
      box-sizing: border-box;
      .foot-left {
        display: flex;
        align-items: center;
        .clear-chat {
          text-align: center;
          background: #ffffff;
          font-size: 12px;
          color: #7c8aa7;
          cursor: pointer;

          // 在大屏幕缩放时调整位置
          @media screen and (max-width: 1200px),
            screen and (-webkit-min-device-pixel-ratio: 1.5),
            screen and (min-resolution: 144dpi) {
            margin-left: 40px;
          }
          &:hover {
            color: #1c4fe5;
          }
        }

        .upload-btn {
          margin-left: 10px;
          margin-bottom: 3px;
          span {
            font-size: 12px;
            color: #7c8aa7;
            i {
              font-size: 12px;
              margin-right: 3px;
            }
            &:hover {
              color: #1c4fe5;
              background-color: #fff;
            }
          }
        }
      }
      .foot-right {
        transform: translateY(-5px);
        .send-button {
          background-color: #1c4fe5; /* 按钮背景色 */
          border: none;
          background: #2a6ee9;
          border-radius: 10px;
          text-align: center;
          cursor: pointer; /* 鼠标指针 */
        }
        .send-button img {
          width: 20px; /* 图标宽度 */
          height: 20px; /* 图标高度 */
        }

        .send-button:hover {
          background-color: #1c4fe5; /* 悬停时的背景色 */
        }
      }
    }
  }
  // 修改滚动条样式
  ::-webkit-scrollbar {
    width: 5px;
    background-color: #f5f5f5;
  }
  ::-webkit-scrollbar-thumb {
    background-color: #ccc;
    border-radius: 3px;
  }

  // 数字人
  .shuziren {
    position: absolute;
    right: 8px;
    bottom: 157px;
    z-index: 99;
    display: flex;
    justify-content: center;
    align-items: flex-start;
    gap: 5px;
    .img {
      width: 124px;
      height: 145px;
      img {
        width: 100%;
        height: 100%;
        object-fit: cover;
      }
    }
  }
}

.selected-file {
  border: 1px solid #cdd2df; // 设置选中时的边框颜色
  .circle {
    position: absolute;
    bottom: 5px;
    right: 5px;
    width: 12px;
    height: 12px;
    z-index: 99;
  }
}

.circle {
  position: absolute;
  bottom: 5px;
  right: 5px;
  width: 12px;
  height: 12px;
  z-index: 99;
}

.quote-box {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 10px;
  background: #f3f4fa;
  border-radius: 8px;
  margin-bottom: 10px; // 与输入框的间距
}

.quote-box-user {
  display: flex;
  justify-content: space-between;
  align-items: center;
  background: #e0e4f9;
  border-radius: 8px;
  margin-bottom: 10px; // 与输入框的间距
}

.quoted-content {
  flex: 1; // 让内容占据剩余空间
  margin-right: 10px; // 右侧间距
  overflow: hidden; // 超出部分隐藏
  white-space: nowrap; // 不换行
  text-overflow: ellipsis; // 超出部分用省略号表示
}

.quoted-content-user {
  flex: 1; // 让内容占据剩余空间
  overflow: hidden; // 超出部分隐藏
  white-space: nowrap; // 不换行
  text-overflow: ellipsis; // 超出部分用省略号表示
  color: #6670a5;
}

.loading-dots {
  display: flex;
  justify-content: flex-start;
  align-items: center;
  padding: 20px;

  span {
    display: inline-block;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background-color: #1c4fe5;
    margin-right: 5px;
    animation: loading 1.4s infinite ease-in-out both;

    &:nth-child(1) {
      animation-delay: -0.32s;
    }

    &:nth-child(2) {
      animation-delay: -0.16s;
    }
  }
}

@keyframes loading {
  0%,
  80%,
  100% {
    transform: scale(0);
  }
  40% {
    transform: scale(1);
  }
}
</style>
